{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 变量、对象和引用[B1P185-186]\n",
    "变量永远不会拥有和它关联的类型信息或约束。类型的概念存在于对象而不是变量中。变量原本是通用的，他只是在一个特定的时间点，简单地引用了一个特定的对象而已。\n",
    "当变量出现在表达式中时，它会马上被当前引用的对象所替换，无论这个对象是什么类型。此外，所有的变量必须在使用前明确地被赋值，使用未赋值的变量会产生错误。\n",
    "简而言之，变量在赋值的时候才会被创建，它可以引用任何类型的对象，而且必须在引用之前赋值。\n",
    "语句 a=3,变量a实际是到对象内存空间（通过运行常量表达式3而创建）的一个指针。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 类型属于对象，而不是变量[B1P187]\n",
    "a = 3 \n",
    "a = 'spam' \n",
    "a = 1.23\n",
    "变量名没有类型，类型属于对象，而不是变量。我们只是将变量修改为对不同变量的引用。只是让不同的变量名引用不同类型的对象。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 对象的垃圾回收[B1P187]\n",
    "a = 3\n",
    "a = 'spam'\n",
    "a 引用的对象的类型改变，对象的引用值在此过程中逐个丢弃。a每次被赋值给一个新对象时，python都会回收之前对象的空间。在内部，python在每个对象中保留了一个计数器，计数器记录该对象的引用数目，一旦这个计数器被设置为0，这个对象的内存空间就会被回收。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 共享引用\n",
    "a = 3\n",
    "b = a\n",
    "a = 'spam'\n",
    "最开始a,b两个变量通过各自的引用指向了同一个对象，之后a改变引用，但b仍然指向3所在的内存空间，并不会因为a指向了新的对象就被回收。没有办法改变3的值，整数不可变。没有办法在原位置改变它。在python中变量总是一个指向对象的指针，而不是可改变的内存区域的标签，给一个变量赋一个新值，并不是替换原有的对象，而是让这个变量去引用一个完全不同的对象。[B1P190]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[24, 3, 4]\n",
      "[24, 3, 4]\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# 共享引用与原位置修改\n",
    "l1 = [2,3,4]\n",
    "l2 = l1\n",
    "l1[0] = 24\n",
    "print(l1)\n",
    "print(l2)\n",
    "print(l1 is l2) #  is 判断对象是否相等，如果两个变量名指向同一个对象就返回 True.实际上is只是比较了实现引用的指针。\n",
    "# 这里改变l1[0]都改变了，是因为l1与l2都指向[2,3,4]所在的内存，即指针l1,l2未改变，只是列表中[2,3,4]是可变类型，修改了值而已。\n",
    "# 从技术上来说，列表就像 C 语言中的指针数组，列表里包含了零个或多个其它对象的引用[B1P246]。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[24, 3, 4]\n",
      "[2, 3, 4]\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "l1 = [2,3,4]\n",
    "l2 = l1[:]\n",
    "l1[0] = 24\n",
    "print(l1)\n",
    "print(l2)\n",
    "print(l1 is l2)\n",
    "# 这里l2是对l1内容的复制，他们在内存中的空间不同，即l1，l2指向不同的内存。改变l1指向的内存空间的位置对l2无影响。\n",
    "# 因为列表是序列，可用分片进行赋值，但要复制一个字典和集合应该用x.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
